package com.huanzhidadi.java8inaction.chapter6;

import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.LongStream;
import java.util.stream.Stream;

public class ParallelTest {

    /**
     * 串行处理，对所有数字求和
     * @param n
     * @return
     */
    public static long sequentialSum(long n) {
        return Stream.iterate(1L, i -> i + 1)
                .limit(n)
                .reduce(0L, Long::sum);
    }

    /**
     * 并行处理，对所有数字求和
     * @param n
     * @return
     */
    public static long parallelSum(long n) {
        return Stream.iterate(1L, i -> i + 1)
                .limit(n)
                .parallel()
                .reduce(0L, Long::sum);
    }

    /**
     * 对处理时间进行测量
     * @param adder
     * @param n
     * @return
     */
    public static long measureSumPerf(Function<Long, Long> adder, long n) {
        long timeUse = 0L;
        for (int i=0; i<10; i++) {
            long start = System.nanoTime();
            long sum = adder.apply(n);
            long duration = (System.nanoTime() - start) / 1_000_000;
            System.out.println("result: " + sum);
            // 取10次的平均值
            timeUse += duration;
        }
        return timeUse / 10;
    }

    public static void main(String[] args) {
//        long result = measureSumPerf(ParallelTest::sequentialSum, 10_000_000);
//        System.out.println("串行处理耗时：" + result + " ms");

//        long result = measureSumPerf(ParallelTest::parallelSum, 10_000_000);
//        System.out.println("并行处理耗时：" + result + " ms");



//        long result = measureSumPerf(ParallelTest::rangedSum, 1000_000_000);
//        System.out.println("串行指定数字范围处理耗时：" + result + " ms");

        long result = measureSumPerf(ParallelTest::parallelRangedSum, 1000_000_000);
        System.out.println("并行指定数字范围处理耗时：" + result + " ms");

        Logger.getAnonymousLogger().log(Level.INFO, () -> "sssssssss");
    }

    /**
     * 串行指定数字范围
     * @param n
     * @return
     */
    public static long rangedSum(long n) {
        return LongStream.rangeClosed(1, n)
                .reduce(0L, Long::sum);
    }

    /**
     * 并行指定数字范围
     * @param n
     * @return
     */
    public static long parallelRangedSum(long n) {
        return LongStream.rangeClosed(1, n)
                .parallel()
                .reduce(0L, Long::sum);
    }
}
